import copy
import traceback

import pygame
import PygameCrew as pycr
from calca import symbol

import asset.startup_check
from asset.base import *
from asset.constants import *
from control import *
from editor_control import *

pycr.pcv.caption="Elivo Editor    version " + version_string
pycr.pcv.length,pycr.pcv.width=1536, 864
pycr.pcv.icon=imgs.ico_editor
pycr.screen=pycr.pcv.set_window()
BUTSIZE=(200,35)
BUTSIZE_BIGGER=(BUTSIZE[0]*1.5,BUTSIZE[1])
def addoption(allstring:str,option_to_add:str):
    tmp=allstring.split(SEPARATOR)
    tmpstring=tmp[-1]
    option=tmp[0] if len(tmp)>1 else ""
    if option_to_add in option:option=option.replace(option_to_add,"")
    else:option=setofstring(option,option_to_add)
    if len(option)>0:return option+SEPARATOR+tmpstring
    else:return tmpstring
def copyobject(obj:Game_Blocks,pos:pycr.Pos):
    result=copy.deepcopy(obj)
    result.rect.absolute(*pos)
    if isinstance(result.feature,dict):
        for f,option in result.feature.items():
            try:
                spec, trig=option
                if isinstance(spec,dire):
                    spec.absolute(pos)
            except:...
    return result
def editor(_all=None,name=None,version=None,location:str=None):
    qsave=True
    pygame.key.set_repeat(500,30)
    pygame.mouse.set_visible(False)
    try:
        FEATURE_POS=(10,50)
        if _all is None:_all,name,version,location=startup(location)
        last=list()
        loop=True
        but_platform=pycr.button((0,0),(100,30),double("Platform"))
        but_killer=pycr.button((100,0),(200,30),double("Killer"))
        but_warp=pycr.button((200,0),(300,30),double("Warp"))
        but_clear=pycr.button((1486,0),(1536,30),double("Clear"))
        but_save=pycr.button((1400,0),(1486,30),double("Save"))
        but_motion=pycr.button((350,0),(450,30),double("Motion"))
        but_advanced=pycr.button((450,0),(550,30),double("Advanced"))
        but_text=pycr.button((550,0),(650,30),double("Insert"))
        but_config=pycr.button((750,0),(850,30),double("Config"))
        but_utilities=pycr.button((1300,0),(1400,30),double("Utilities"))
        but_more=pycr.button((650,0),(750,30),double("More"))
        edit_motion,edit_trigger,edit_textbox,edit_timer,edit_hook,edit_conveyor,edit_wind,view_existing,edit_water=objects(9)
        edit_pushblock,edit_whatever=objects(2)
        ipt_speed,ipt_respond=pycr.serie_inputbox((0,600),BUTSIZE,"Speed","Respond")
        but_chase,but_shoot=pycr.serie_button((0,690),BUTSIZE,"Chase","Aiming")
        wid_movetype=pycr.window((0,64),(1536,800),title="Motion Editor Window",
                    body="""Please choose an edit mode
single - Stops after the motion
repeat - Go back to start place every time and continue doing a motion
turn - Turn back on touching the both ends

Also, input the trigger number in the second box(default: start immediately)

You need to select some items to use a motion.
Select by put mouse cursor on it then press S key.
Press again to dis-select.
""",textsize=25,
                    bottombuttons=("Exit","Single","Repeat","Turn","Appear",ipt_speed,ipt_respond,but_chase,but_shoot),
                    bottomsize=BUTSIZE)
        ipt_text=pycr.inputbox((0,200),(1536,740),textsize=35,terminate_on_return=False,textpos=(10,210),default_text="Ctrl + Alt + C to clear all text")
        wid_text=pycr.window((0,64),(1536,800),title="Text Editor Window",
                    body="""Please type the text to insert""",textsize=25,
                    bottombuttons=("Exit","Put Textbox",ipt_text),
                    bottomsize=BUTSIZE)
        ipt_advanced,ipt_advanced_second,ipt_advanced_third=pycr.serie_inputbox((0,690),BUTSIZE,"Trigger","Time","Respond")
        but_anti,but_instant,but_rapid,but_existing=pycr.serie_button((0,640),BUTSIZE,"Anti-Trigger","Instant-Trigger","Rapid-Trigger","Existing")
        wid_advanced=pycr.window((0,64),(1536,800),title="Advanced Editor Window",
                    body="""Please choose an edit mode

Input in the box can change the object's features.""",textsize=25,
                    bottombuttons=("Exit","Trigger","Timer",ipt_advanced,ipt_advanced_second,ipt_advanced_third,
                                   but_anti,but_existing,but_instant,but_rapid),
                    bottomsize=BUTSIZE)
        ipt_config=pycr.inputbox((0,690),(1536,740),textsize=35,limit=80,default_text="Configuration Text")
        wid_config=pycr.window((0,64),(1536,800),title="Level Configurations Window",
                    body="""Please enter the text you wish to configure.""",textsize=25,
                    bottombuttons=("Exit","Name","Version",ipt_config),
                    bottomsize=BUTSIZE)
        ipt_xspeed,ipt_yspeed=pycr.serie_inputbox((0,600),BUTSIZE,"X","Y")
        but_more1=pycr.serie_button((0,700),BUTSIZE,"Water","Push Block")
        wid_more=pycr.window((0,64),(1536,800),title="More Blocks Window",
                    body="""Please choose a block to enter""",textsize=25,
                    bottombuttons=("Exit","Hook","Conveyor","Wind",*but_more1,ipt_yspeed,ipt_xspeed),
                    bottomsize=BUTSIZE)
        buts_gridsize=pycr.serie_button((10,700),BUTSIZE,"Grid:32","Grid:16","Grid:8","Grid:No Grid")
        buts_visible=pycr.serie_button((10,650),BUTSIZE,"Visible:Yes","Visible:No")
        buts_copy=pycr.serie_button((pycr.overlap2(buts_visible[-1].innerrect.ru,(20,0))[0],650),BUTSIZE_BIGGER,"Copy:Copy&Paste","Copy:Disable")
        wid_util=pycr.window((0,64),(1536,800),title="Utilities",
                                 body="""Choose options below""",
                                 bottombuttons=buts_gridsize+buts_visible+buts_copy)
        selected:Game_Blocks=None
        tp_existing=None
        locking=False
        triggermode=True
        mode,editmode,speed,adv_edit,startp,tvr=objects(6,givenone)
        drawers=(but_platform,but_killer,but_warp,edit_trigger,edit_conveyor,edit_wind,edit_water,edit_pushblock)
        show_cursor=drawers+(edit_hook,edit_textbox)
        unblockable_draw=(edit_motion,)
        buttons_rect=pycr.VerRect((0,0),(pycr.PyCr_Value.length,30))
        Visible=True
        CopySwitch=CopySwitch_Short=False
        Can_Perform_Draw=True
        Each=None;Grid=pycr.NOTEXT
        def addobject(o:Game_Blocks):
            _all.append(o)
            if isinstance(o,Game_Blocks):
                if not Visible:
                    makeeditmode(o,"Visible",False)
                    o.feature["Visible"]=False
        while loop:
            pycr.screen.fill(EDIT_BACKGROUND)
            pycr.get_interact()
            pycr.screen.blit(Grid,(0,0))
            ps=pycr.puts(but_platform,but_killer,but_warp,but_clear,but_save
                         ,but_motion,but_advanced,but_text,but_config,but_more,but_utilities)
            #Change mouse position
            MousePos=pycr.PyCr_Value.mouse
            if MousePos in buttons_rect:
                Can_Perform_Draw=False
            if Each is not None and not pycr.PyCr_Value.mod & pygame.KMOD_ALT:
                MousePos = (rbystr(MousePos[0]/Each)*Each,rbystr(MousePos[1]/Each)*Each)
            #Change mode according to buttons
            for p in ps:
                if p[1]:mode=p[0]
            if (but_clear,True) in ps:
                if pyautogui.confirm("Do you really want to clear all objects?","Clear Confirm",("Yes","No")) == "Yes":
                    _all=list()
                    selected=None
            elif (but_save,True) in ps:
                exit_save(_all,name,version)
            elif (but_motion,True) in ps:triggermode=True
            # Defaults
            Copy_Able=(CopySwitch or CopySwitch_Short) and selected is not None
            if Copy_Able:mode=None
            #Shortcut keys
            if pycr.PyCr_Value.key != None:
                if pycr.PyCr_Value.ctrl:
                    if pycr.PyCr_Value.key == pygame.K_2:Each=8
                    elif pycr.PyCr_Value.key == pygame.K_3:Each=16
                    elif pycr.PyCr_Value.key == pygame.K_4:Each=32
                    elif pycr.PyCr_Value.key in (pygame.K_0,pygame.K_1):Each=None
                    if Each is not None:Grid=imgs.loadgrid(str(Each))
                    else:Grid=pycr.NOTEXT
                elif mode in drawers or mode is None:
                    if pycr.PyCr_Value.key == pygame.K_m:mode=but_motion
                    elif pycr.PyCr_Value.key == pygame.K_c:mode=but_more
                    elif pycr.PyCr_Value.key == pygame.K_a:mode=but_advanced
                    elif pycr.PyCr_Value.key == pygame.K_x:mode=None
                    elif pycr.PyCr_Value.key == pygame.K_1:mode=but_platform
                    elif pycr.PyCr_Value.key == pygame.K_2:mode=but_killer
                    elif pycr.PyCr_Value.key == pygame.K_3:mode=but_warp
                if pycr.PyCr_Value.key == pygame.K_u:mode=but_utilities
                if pycr.PyCr_Value.key == pygame.K_DELETE:
                    try:_all.remove(selected)
                    except:...
            # Holding short key
            CopySwitch_Short=pycr.PyCr_Value.press[pygame.K_d]
            
            '''try:laststring
            except:laststring=None
            thisstring=str(pycr.PyCr_Value.left)+" "+str(locking)
            if thisstring != laststring:
                print(thisstring)
            laststring=thisstring'''
            #Append left-click objects
            if pycr.PyCr_Value.leftclick:
                if Can_Perform_Draw:
                    if Copy_Able:
                        obj=copyobject(selected,MousePos)
                        addobject(obj)
                    elif mode is edit_textbox:
                        addobject(text_part(MousePos,adv_edit,color=REVLIGHT))
                    elif mode is edit_timer:
                        addobject(timer(MousePos,ORANGE,float(adv_subedit),adv_edit,adv_3rdedit))
                    elif mode is edit_hook:
                        addobject(hook(MousePos,pycr.overlap2(MousePos,HOOK_SIZE),WHITE))
                if editmode in StructureMotion and selected is not None:
                    cleareditmode(selected,editmode,list())
                    if editmode == "appear":
                        selected.feature[editmode].extend((Appear,triggermode))
                        selected.feature["Appear"]=False
                    elif editmode == "chase":
                        selected.feature[editmode].extend(([speed],triggermode))
                    elif editmode == "aiming":
                        selected.feature[editmode].extend(([speed],triggermode))
                    imgs.sound_click.play()
                    editmode=None
                    selected=None
                if Can_Perform_Draw or mode in unblockable_draw:
                    locking=True
                    startp=MousePos
            #Append dragging objects
            elif not pycr.PyCr_Value.left and locking:
                if pycr.distance(MousePos,startp) >= WARNING_DISTANCE:
                    if mode is but_platform:
                        addobject(platform(rrange.start,rrange.end,PLATFORM))
                    elif mode is but_killer:
                        addobject(killer(rrange.start,rrange.end,KILLER))
                    elif mode is but_warp:
                        addobject(warp(rrange.start,rrange.end,WARP))
                    elif mode is edit_conveyor:
                        addobject(conveyor(rrange.start,rrange.end,CONVEYOR,(adv_edit,adv_subedit)))
                    elif mode is edit_wind:
                        addobject(wind(rrange.start,rrange.end,WIND,(adv_edit,adv_subedit)))
                    elif mode is edit_pushblock:
                        addobject(push_block(rrange.start,rrange.end,PUSH_BLOCK))
                    elif mode is edit_motion and selected is not None:
                        cleareditmode(selected,editmode,list())
                        if editmode in RealMotion:
                            PS=selected.rect.start;PE=sgo(startp,MousePos,selected.rect.start)
                            #if PS[0] == PE[0]:PE=(PE[0]+0.001,PE[1])
                            selected.feature[editmode].extend((dire(PS,PE,speed),triggermode))
                            imgs.play_click()
                        triggermode=True
                        selected=None
                    elif mode is edit_trigger:
                        addobject(trigger(rrange.start,rrange.end,TRIGGER,adv_edit))
                    elif mode is edit_water:
                        addobject(water(rrange.start,rrange.end,WATER_BLUE))
                elif isinstance(selected,Game_Blocks) and pycr.PyCr_Value.mouse not in selected.rect:
                    selected=None
                locking=False
                startp=None
            #Disable selection
            dest_rev:"dict[pycr.Pos,pygame.Surface]"=dict() #Used to draw outlines
            #Detect existing objects
            Can_Perform_Draw=pycr.PyCr_Value.mouse not in buttons_rect
            for obj in _all:
                if pycr.PyCr_Value.mouse in obj.rect:
                    Can_Perform_Draw=pycr.PyCr_Value.press[pygame.K_s]
                    if pycr.PyCr_Value.right:
                        try:_all.remove(obj)
                        except:...
                    elif pycr.PyCr_Value.leftclick and not pycr.PyCr_Value.press[pygame.K_s]:selected=obj
                    result=getrev(obj)
                    dest_rev[result[1]]=result[0]
                editput(obj)
            #Actually draw outline
            for pos,surf in dest_rev.items():pycr.screen.blit(surf,pos)
            if selected is not None:
                drawrev(selected,4)
                if pycr.PyCr_Value.press[pygame.K_f]:
                    pycr.screen.fill(EDIT_BACKGROUND)
                    pycr.put(pycr.text_part(FEATURE_POS,mkdoc(selected),30,color=reverse(selected.color)))
                if selected not in _all:selected=None
            #Detect events
            for event in pycr.get_event():
                if event.type == pygame.QUIT:loop=False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:loop=False
                    elif event.key == pygame.K_w:
                        if pycr.PyCr_Value.ctrl:
                            pygame.mouse.set_visible(True)
                            result=pyautogui.confirm("Save current file before editing another level?","Saving Confirm",("Yes","No","Cancel"))
                            if result == "Yes":exit_save(_all,name,version)
                            if result in ("Yes","No"):_all,name,version,location=startup()
            #Mode windows:
            if mode is but_motion:
                result=pycr.put(wid_movetype)
                if result is not None:
                    if isinstance(result,tuple):
                        if exitnone(result[0]):
                            mode=None
                            continue
                        speed=None
                        speedm=result[1]
                        try:speed=float(speedm)
                        except:...
                        if speed is None:continue
                        editmode=result[0].lower()
                        triggermode=result[2]
                        triggermode=maketrue(triggermode)
                        mode = edit_motion
            elif mode is but_advanced:
                result=pycr.put(wid_advanced)
                if isinstance(result,tuple):
                    but,inputing,second,third=result
                    adv_edit:str=inputing
                    adv_subedit:str=second
                    adv_3rdedit:str=third
                    if exitnone(but):
                        mode=None
                        continue
                    elif but == "Trigger":
                        mode=edit_trigger
                    elif but == "Timer":
                        adv_edit=maketrue(adv_edit)
                        adv_3rdedit=maketrue(adv_3rdedit)
                        if not isfloat(adv_subedit):continue
                        mode=edit_timer
                    elif but == "Anti-Trigger":
                        ipt_advanced.inputing=addoption(inputing,ANTI)
                    elif but == "Instant-Trigger":
                        ipt_advanced.inputing=addoption(inputing,INSTANT)
                    elif but == "Rapid-Trigger":
                        ipt_advanced.inputing=addoption(inputing,RAPID)
                    elif but == "Existing":
                        mode=view_existing
            elif mode is but_text:
                result=pycr.put(wid_text)
                if isinstance(result,tuple):
                    but,inputing=result
                    adv_edit=inputing
                    if exitnone(but):
                        mode=None
                        continue
                    elif but == "Put Textbox":
                        mode=edit_textbox
            elif mode is but_config:
                result=pycr.put(wid_config)
                if isinstance(result,tuple):
                    but,inputing=result
                    if exitnone(but):
                        mode=None
                        continue
                    elif but == "Name":
                        name=inputing
                    elif but == "Version":
                        version=inputing
                    mode=None
            elif mode is but_more:
                result = pycr.put(wid_more)
                if isinstance(result,tuple):
                    but=result[0]
                    y=result[1]
                    x=result[2]
                    if exitnone(but):
                        mode=None
                        continue
                    elif but == "Hook":
                        mode=edit_hook
                    elif but == "Conveyor":
                        if not isfloat(x):continue
                        if not isfloat(y):continue
                        adv_edit=float(x)
                        adv_subedit=float(y)
                        mode=edit_conveyor
                    elif but == "Wind":
                        if not isfloat(x):continue
                        if not isfloat(y):continue
                        adv_edit=float(x)
                        adv_subedit=float(y)
                        mode=edit_wind
                    elif but == "Water":mode=edit_water
                    elif but == "Push Block":mode=edit_pushblock
            elif mode is but_utilities:
                result=pycr.put(wid_util)
                if isinstance(result,str):
                    but=result
                    Actual=but.split(':')[-1]
                    if but.startswith("Grid:"):
                        Grid=imgs.loadgrid(Actual)
                        if Grid is not pycr.NOTEXT:Each=int(Actual)
                        else:Each=None
                    elif but.startswith("Visible:"):
                        Visible = Actual=="Yes"
                    elif but.startswith("Copy:"):
                        CopySwitch = Actual!="Disable"
                    mode=None
            elif mode is view_existing:
                if tp_existing is None:
                    text="Left click to escape trigger view.\nExisting Triggers:\n"
                    for load in _all:
                        if isinstance(load,(trigger,timer)):text+=load.__class__.__name__+" at "+str(load.rect.start)+" : "+str(load.trig)+"\n"
                    tp_existing=pycr.text_part((10,10),text,30,color=REVEDIT_BACKGROUND)
                pycr.screen.fill(EDIT_BACKGROUND)
                pycr.put(tp_existing)
                if pycr.PyCr_Value.leftclick:mode=tp_existing=None
            #Locking detection
            if locking:
                if mode in drawers:
                    rrange=pycr.VerRect(startp,MousePos)
                    pygame.draw.rect(pycr.screen,BLACK,rrange.rectvalue)
                elif mode is edit_motion and editmode in RealMotion and selected is not None:
                    pygame.draw.line(pycr.screen,BLACK,selected.rect.start,sgo(startp,MousePos,selected.rect.start),3)
            #Blit the mouse cursor
            if pygame.mouse.get_visible():
                pygame.mouse.set_visible(False)
            if CopySwitch or CopySwitch_Short:
                pycr.screen.blit(imgs.img_copycursor,MousePos)
            elif mode in show_cursor:
                PutPlace=pycr.overlap2(MousePos,(0,-imgs.size_markarrow[1]))
                pycr.screen.blit(imgs.img_markarrow,PutPlace)
            else:
                if not pygame.mouse.get_visible():
                    pygame.mouse.set_visible(True)
            pycr.clock.tick(50)
            pygame.display.flip()
    except:
        trace=traceback.format_exc()
        print(trace)
    pygame.mouse.set_visible(True)
    return _all,name,version,location
if __name__ == "__main__":
    if len(sys.argv) > 1:
        igvar["location"]=mltsplit(sys.argv[1],'/','\\')[-1]
    _all=name=version=location=None
    while True:
        _all,name,version,location=editor(_all,name,version,location)
        result=pyautogui.confirm("Save current file before exit?","Saving Confirm",("Yes","No","Cancel"))
        if result == "Yes":exit_save(_all,name,version)
        elif result == "Cancel":continue
        break
